<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>jQuery + Layui 双向绑定</title>
  <!-- 使用 BootCDN 提供的 Layui CSS -->
  <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/layui/2.8.0/css/layui.min.css">
  <!-- 使用 BootCDN 提供的 jQuery -->
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <!-- 使用 BootCDN 提供的 Layui JS -->
  <script src="https://cdn.bootcdn.net/ajax/libs/layui/2.8.0/layui.min.js"></script>
  <style>
    .user-item {
      margin-bottom: 10px;
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
    }
    .user-item input {
      margin-right: 10px;
    }
    button {
      margin-top: 10px;
    }
  </style>
</head>
<body>
  <div class="layui-container">
    <div id="userList">
      <!-- 列表项模板 -->
      <script type="text/html" id="userTemplate">
        {{# layui.each(d.users, function(index, item){ }}
          <div class="user-item">
            <input type="text" data-bind="users.{{index}}.name" value="{{item.name}}" placeholder="Name">
            <input type="text" data-bind="users.{{index}}.age" value="{{item.age}}" placeholder="Age">
            <button data-action="remove" data-method="removeUser" data-index="{{index}}">Remove</button>
          </div>
        {{# }); }}
      </script>
    </div>
    <button data-action="add" data-method="addUser" class="layui-btn">Add User</button>
  </div>

  <script>
    layui.use(['laytpl'], function() {
      const laytpl = layui.laytpl;

      // 定义数据模型和方法
      const data = {
        users: [
          { name: "John", age: 25 },
          { name: "Jane", age: 30 }
        ],
        addUser: function() {
          this.users.push({ name: "", age: "" });
          renderView();
        },
        removeUser: function(index) {
          this.users.splice(index, 1);
          renderView();
        }
      };

      // 渲染视图
      function renderView() {
        const html = laytpl($('#userTemplate').html()).render(data);
        $('#userList').html(html); // 重新渲染视图
        bindEvents(); // 重新绑定事件
        bindTwoWay(data); // 重新绑定双向绑定
      }

      // 通用事件注册方法
      function bindEvents() {
        // 绑定方法调用事件
        $('[data-method]').on('click', function() {
          const method = $(this).data('method');
          const index = $(this).data('index');
          if (data[method]) {
            data[method].call(data, index);
          }
        });
      }

      // 通用双向绑定方法
      function bindTwoWay(model) {
        $('[data-bind]').each(function() {
          const $element = $(this);
          const bindKey = $element.data('bind');
          const keys = bindKey.split('.');
          let target = model;
          for (let i = 0; i < keys.length - 1; i++) {
            target = target[keys[i]];
          }
          const property = keys[keys.length - 1];

          // 初始化视图
          $element.val(target[property]);

          // 视图变化时更新数据模型
          $element.on('input', function() {
            target[property] = $element.val();
            console.log('Data:', model);
          });

          // 数据模型变化时更新视图
          if (!target.__isObserved) {
            Object.defineProperty(target, property, {
              get: function() {
                return this._value;
              },
              set: function(newValue) {
                this._value = newValue;
                $element.val(newValue);
              }
            });
            target.__isObserved = true;
          }
        });
      }

      // 初始化渲染
      renderView();
    });
  </script>
</body>
</html>